package com.demo.config.socket;

import com.demo.common.base.R;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

//value 映射地址，encoders 编码器，对传递的参数进行处理
@ServerEndpoint(value = "/websocket/{token}", encoders = {ResultEncoder.class})
@Component
public class WebSocket {


    private static int onLineNumber;

    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话，可以使用Map来存放，其中Key可以为用户标识
    public static Map<String, Session> electricSocketMap = new ConcurrentHashMap<String, Session>();

    /**
     * 连接建立成功调用的方法
     *
     * @param session 可选的参数。session为与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    @OnOpen
    public void onOpen(@PathParam("token") String token, Session session) {

        electricSocketMap.put(token, session);

        sendMsg(session, new R().data("成功"));
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("token") String token, Session session) {
        if (electricSocketMap.containsKey(token)) {
            electricSocketMap.remove(token);
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("websocket received message:" + message);
        String[] split = message.split("--");
        if (split[1].contains("0")) {
            //发送消息给所有人
            sendAll(message);
        } else {
            //发送消息给指定用户
            sendMsg(electricSocketMap.get(split[1]), message);
        }
    }

    /**
     * 发生错误时调用
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }

    /**
     * @param session
     * @param message 消息结果集
     */
    public static void sendMsg(Session session, Object message) {
        try {
            session.getBasicRemote().sendObject(message);
        } catch (Exception e) {
            e.printStackTrace();

        }
    }

    /**
     * 群发消息
     *
     * @param message 消息内容
     */
    private void sendAll(Object message) {
        for (Map.Entry<String, Session> sessionEntry : electricSocketMap.entrySet()) {
            sessionEntry.getValue().getAsyncRemote().sendObject(message);
        }
    }


    private static synchronized int getAddOnLineNumber() {
        return onLineNumber++;
    }

    private static synchronized int getReduceOnLineNumber() {
        return onLineNumber--;
    }

    private static synchronized int getOnLineNumber() {
        return onLineNumber;
    }

}